#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project ：PythonProjects
@File    ：op.py
@IDE     ：PyCharm
@Author  ：pipibao
@Date    ：2021/7/3 下午4:07
'''

import cv2 as cv
import numpy as np


# 像素取反
def get_img_reserve(img):
    dst = cv.bitwise_not(img)
    # cv.imshow("reserve",dst)
    # cv.waitKey()
    # cv.destroyAllWindows()
    return dst


def to_be_HSV(image):
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
    return hsv


def to_be_Gray(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    return gray


def image_binarization(img):
    # 将图片转为灰度图
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    retval, dst = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)
    cv.imwrite('binary.jpg', dst)
    return dst


def Gaussian_blur(image):
    blur = cv.GaussianBlur(image, (5, 5), 0)
    return blur


def get_image_info(image, op):
    T = type(image)
    S = image.shape
    if op == "type":
        return T
    elif op == "size":
        return S[1], S[0]
    elif op == "byte":
        return image.size


def resize(image):
    w, h = get_image_info(image, "size")
    a = 250 / h
    return cv.resize(image, (int(a * w), int(a * h)))


def erode(image, a, b):  # 黑底白图为膨胀
    ret, binary = cv.threshold(image, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (a, b))
    dst = cv.erode(binary, kernel)
    return dst


def dilate(image, a, b):  # 黑底白图为侵蚀
    ret, binary = cv.threshold(image, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (a, b))
    dst = cv.dilate(binary, kernel)
    return dst


def open_operate(image, a=5, b=5):
    image1 = dilate(image, a, b)
    dst = dilate(image1, a, b)
    return dst


def close_operate(image, a, b):
    image2 = erode(image, a, b)
    dst = erode(image2, a, b)
    return dst


def contrast_brightness(image, c, b):  # c为饱和度，b为亮度
    h, w, ch = image.shape
    blank = np.zeros([h, w, ch], image.dtype)
    dst = cv.addWeighted(image, c, blank, 1 - c, b)
    return dst


def shift_filter(image):  # 均值迁移
    dst = cv.pyrMeanShiftFiltering(image, 25, 50)
    return dst


def cut_image(image, cnt):
    min_x = 10000
    max_x = 0
    min_y = 10000
    max_y = 0
    for i in cnt:
        min_x = min(min_x, i[1])
        min_y = min(min_y, i[0])
        max_x = max(max_x, i[1])
        max_y = max(max_y, i[0])
    print(min_x, max_x, min_y, max_y)
    f = (max_y - min_y) / (max_x - min_x)
    if 2.4 < f < 4:
        return True, image[min_x + 2:max_x, min_y + 2:max_y]
    else:
        return None, image[min_x:max_x, min_y:max_y]


def angle_cos(p0, p1, p2):  # 计算两边夹角额cos值
    d1, d2 = (p0 - p1).astype('float'), (p2 - p1).astype('float')
    return abs(np.dot(d1, d2) / np.sqrt(np.dot(d1, d1) * np.dot(d2, d2)))


def find_squares(img, src):
    squares = []
    # img = cv.GaussianBlur(img, (3, 3), 0)
    # gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    bin = cv.Canny(img, 30, 100, apertureSize=3)
    contours, heriachy = cv.findContours(bin, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    contours2, heriachy = cv.findContours(bin, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    print("轮廓数量：%d" % len(contours))
    index = -1
    # 轮廓遍历
    for cnt in contours:
        index = index + 1
        cnt_len = cv.arcLength(cnt, True)  # 计算轮廓周长
        cnt = cv.approxPolyDP(cnt, 0.02 * cnt_len, True)  # 多边形逼近
        # 条件判断逼近边的数量是否为4，轮廓面积是否大于1000，检测轮廓是否为凸的
        if len(cnt) == 4 and cv.contourArea(cnt) > 1000 and cv.isContourConvex(cnt):
            M = cv.moments(cnt)  # 计算轮廓的矩
            cx = int(M['m10'] / M['m00'])
            cy = int(M['m01'] / M['m00'])  # 轮廓重心

            cnt = cnt.reshape(-1, 2)
            max_cos = np.max([angle_cos(cnt[i], cnt[(i + 1) % 4], cnt[(i + 2) % 4]) for i in range(4)])
            # 只检测矩形（cos90° = 0）
            if max_cos < 0.1:
                squares.append(cnt)
                cv.drawContours(src, [contours2[index]], -1, (0, 0, 255), 3)
    return squares, src


def hsv_color_room(color):
    """
    :param color:a string of name of color
    :return: 两个数组：low&high
    """
    low = [0, 0, 0]
    high = [180, 255, 255]
    if color == "blue":
        low = [100, 100, 46]
        high = [124, 255, 240]
    elif color == "green":
        low = [35, 70, 46]
        high = [77, 255, 240]
    elif color == "yellow":
        low = [26, 70, 46]
        high = [34, 255, 255]
    elif color == "white":
        low = [0, 0, 221]
        high = [180, 30, 255]
    return low, high


def check_color(image, low, high):
    """
    :param image:opencv图像格式
    :param low: hsv筛选下限
    :param high: hsv筛选上限
    :return: 色彩筛选后的image
    """
    image_hsv = to_be_HSV(image)
    lower_hsv = np.array(low)
    upper_hsv = np.array(high)
    return cv.inRange(image_hsv, lower_hsv, upper_hsv)
